<?php

Raise::load('core.structure.RaiseDataType');
Raise::load('core.reflection.RaiseVariable');
Raise::load('core.collection.IRaiseCollectionConvertible');

/**
 * RaisePoint class
 * represents a point with the X and Y coordinates
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.core.geometry
 * @since 1.2
 */
class RaisePoint extends RaiseDataType implements IRaiseCollectionConvertible {
    
    /**
     * The X coordinate of the point
     * @var integer|double
     */
    private $x = 0;

    /**
     * The Y coordinate of the point
     * @var integer|double
     */
    private $y = 0;

    /**
     * Creates a new RaisePoint
     * @param integer|double $a The X coordinate of the point
     * @param integer|double $b The Y coordinate of the point
     */
    function __construct($a, $b){
        $this->x($a);
        $this->y($b);
    }

    /**
     * Get or set the X dimension of the RaisePoint object
     * @param integer|double $x (Optional) The X dimension to set
     * @return integer|double
     */
    public function x($x = false){
        if($x !== false){
            if(!RaiseVariable::isNumeric($x)){
                throw new RaiseInvalidArgumentException('$x is not a numeric variable (i.e. integer or double).');
            }
            $this->x = $x;
        }
        return $this->x;
    }

    /**
     * Get or set the Y dimension of the RaisePoint object
     * @param integer|double $y (Optional) The X dimension to set
     * @return integer|double
     */
    public function y($y = false){
        if($y !== false){
            if(!RaiseVariable::isNumeric($y)){
                throw new RaiseInvalidArgumentException('$y is not a numeric variable (i.e. integer or double).');
            }
            $this->y = $y;
        }
        return $this->y;
    }

    /**
     * Converts the point to a collection
     * @return RaiseCollection
     */
    public function toCollection(){
        return new RaiseCollection($this->x, $this->y);
    }
    
    /**
     * Gets the zero,zero point
     * @return RaisePoint
     * @static
     */
    public static function zero(){
        return new RaisePoint(0, 0);
    }

    /**
     * Returns point as a string format "x,y"
     */
    function __toString(){
        return $this->x() . ',' . $this->y();
    }

    /**
     * Compare whether both Point XY values are equal or not
     * @param RaisePoint $o
     * @return boolean
     */
    public function equals($o) {
        return $this->x() == $o->x() && $this->y() == $o->y();
    }

    /**
     * Get the distance between this point and another point
     * @param RaisePoint $p
     * @return integer|double
     */
    public function distance($p){
        $x = abs($p->x() - $this->x());
        $y = abs($p->y() - $this->y());
        return hypot($x, $y);
    }

}